package com.chinatechstar.prediction.service.impl;

import java.io.File;
import java.io.IOException;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import com.alibaba.excel.EasyExcel;
import com.alibaba.fastjson.JSON;
import com.chinatechstar.admin.entity.SysUser;
import com.chinatechstar.admin.mapper.SysUserMapper;
import com.chinatechstar.component.commons.utils.CurrentUserUtils;
import com.chinatechstar.component.commons.utils.FileUtils;
import com.chinatechstar.component.commons.utils.PinyinUtils;
import com.chinatechstar.prediction.dto.PredictionPressureDTO;
import com.chinatechstar.prediction.dto.PredictionPressureDetailDTO;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.chinatechstar.prediction.entity.PredictionPressure;
import com.chinatechstar.prediction.mapper.PredictionPressureMapper;
import com.chinatechstar.prediction.service.PredictionPressureService;
import com.chinatechstar.component.commons.result.PaginationBuilder;
import com.chinatechstar.component.commons.utils.SequenceGenerator;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import java.lang.Math;
import javax.servlet.http.HttpServletResponse;

/**
 * 业务逻辑实现层
 */
@Service
@Transactional
public class PredictionPressureServiceImpl implements PredictionPressureService {

    private final Logger logger = LoggerFactory.getLogger(getClass());
    private static final SequenceGenerator SEQUENCE_GENERATOR = new SequenceGenerator();

    private static final Long FILE_STORAGE_ID=869126385570902016L;
    @Autowired
    private PredictionPressureMapper predictionPressureMapper;
    @Autowired
    private SysUserMapper sysUserMapper;

    /**
     * 查询所有数据
     */
    @Override
    public List<PredictionPressure> findPredictionPressureAll() {
        return predictionPressureMapper.findPredictionPressureAll();
    }

    /**
     * 根据压力和温度查询密度和粘度
     */
    @Override
    public List<PredictionPressureDTO> findWellCo2Density(Double formationPressure, Double formationTemperature) {

        return predictionPressureMapper.findWellCo2Density(formationPressure, formationTemperature);
    }
    /**
     * 查询分页
     */
    @Override
    public Map<String, Object> findPredictionPressureByCondition(Integer currentPage, Integer pageSize, String wellName, String planName, String sorter) {
        Map<String, Object> paramMap = new HashMap<>();
        if (PinyinUtils.isEnglish(wellName)) {
            paramMap.put("pinyin", wellName);
        } else {
            paramMap.put("wellName", wellName);
        }
        paramMap.put("planName", planName);
        if (StringUtils.isNotBlank(sorter)) {
            String sort = sorter.substring(0, sorter.lastIndexOf('_'));
            String sequence = "ascend".equals(sorter.substring(sorter.lastIndexOf('_') + 1)) ? "ASC" : "DESC";
            paramMap.put("sort", sort);
            paramMap.put("sequence", sequence);
        } else {
            paramMap.put("sort", "createTime");
            paramMap.put("sequence", "DESC");
        }
        Page<Object> page = PageHelper.startPage(currentPage, pageSize);
        List<LinkedHashMap<String, Object>> resultList = predictionPressureMapper.findPredictionPressureByCondition(paramMap);
        return PaginationBuilder.buildResult(resultList, page.getTotal(), currentPage, pageSize);
    }

    /**
     * 查询导出数据列表
     */
    @Override
    public List<LinkedHashMap<String, Object>> findPredictionPressureForExcel(Map<String, Object> paramMap) {
        return predictionPressureMapper.findPredictionPressureByCondition(paramMap);
    }
    /**
     * 导出
     */
    @Override
    public void exportPredictionPressure(HttpServletResponse response) throws IOException {
        // 查询数据
        List<PredictionPressure> dataList = predictionPressureMapper.findPredictionPressureAll();

        try {
            String templateFileName = FileUtils.getPath() + "templates" + File.separator + "注入压力预测数据导出模板.xlsx";
            templateFileName = URLDecoder.decode(templateFileName, "utf-8");
            String fileName = URLDecoder.decode("注入压力预测数据导出" + System.currentTimeMillis() + ".xlsx", "utf-8");

            response.setContentType("application/vnd.ms-excel");
            response.setCharacterEncoding("utf-8");
            response.setHeader("Content-disposition", "attachment; filename=" + new String(fileName.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1));

            File file = new File(templateFileName);
            if (file.exists()) {
                EasyExcel.write(response.getOutputStream()).withTemplate(templateFileName).sheet(0).doFill(dataList);
            }
        } catch (Exception e) {
            response.reset();
            response.setContentType("application/json");
            response.setCharacterEncoding("utf-8");
            Map<String, String> resMap = new HashMap<>(2);
            resMap.put("status", "500");
            resMap.put("message", "下载文件失败：" + e.getMessage());
            response.getWriter().println(JSON.toJSONString(resMap));
        }
    }

    /**
    * 根据主键ID数据查询数据
    */
    @Override
    public PredictionPressure findPredictionPressureById(Long id) {
        return predictionPressureMapper.findPredictionPressureById(id);
    }

    /**
    * 根据主键ID数组查询数据
    */
    @Override
    public List<PredictionPressure> findPredictionPressureByIds(Long[] ids) {
        return predictionPressureMapper.findPredictionPressureByIds(ids);
    }

    /**
     * 新增
     */
    @Override
    public void insertPredictionPressure(PredictionPressure predictionPressure) {
        SysUser currUser = sysUserMapper.getUserByUsername(CurrentUserUtils.getOAuth2AuthenticationInfo().get("name"));

        predictionPressure.setId(SEQUENCE_GENERATOR.nextId());
        predictionPressure.setCreateName(currUser.getNickname());
        predictionPressure.setCreateUsername(currUser.getUsername());
        predictionPressure.setAverageDensity(1.0*(predictionPressure.getWellHeadDensity()+ predictionPressure.getWellBottomDensity())/2);
        predictionPressureMapper.insertPredictionPressure(predictionPressure);

        // 创建初始文件
        HashMap<String, String> info = FileUtils.mkdirCommand(String.valueOf(predictionPressure.getId()), FILE_STORAGE_ID, null, predictionPressure.getId());
        logger.info("已新增： {}", predictionPressure.getId());
        logger.info("创建文件夹：{}", info.get("dirName"));
    }

    /**
     * 批量新增
     */
    @Override
    public void insertPredictionPressures(List<PredictionPressure> predictionPressures) {
        SysUser currUser = sysUserMapper.getUserByUsername(CurrentUserUtils.getOAuth2AuthenticationInfo().get("name"));

        for(PredictionPressure predictionPressure : predictionPressures) {
            predictionPressure.setId(SEQUENCE_GENERATOR.nextId());
            predictionPressure.setCreateName(currUser.getNickname());
            predictionPressure.setCreateUsername(currUser.getUsername());
        }
        predictionPressureMapper.insertPredictionPressures(predictionPressures);
    }

    /**
     * 编辑
     */
    @Override
    public void updatePredictionPressure(PredictionPressure predictionPressure) {
        predictionPressureMapper.updatePredictionPressure(predictionPressure);
        logger.info("已编辑： {}", predictionPressure.getId());
    }

    /**
     * 批量编辑
     */
    @Override
    public void updatePredictionPressures(List<PredictionPressure> predictionPressures) {
        predictionPressureMapper.updatePredictionPressures(predictionPressures);
    }

    /**
     * 删除
     */
    @Override
    public void deletePredictionPressureById(Long id) {
        predictionPressureMapper.deletePredictionPressureById(id);
    }

    /**
     * 批量删除
     */
    @Override
    public void deletePredictionPressureByIds(Long[] ids) {
        predictionPressureMapper.deletePredictionPressureByIds(ids);
    }

//    /**
//     * 软删除
//     */
//    @Override
//    public void softDeletePredictionPressureById(Long id) {
//        PredictionPressure predictionPressure = predictionPressureMapper.findPredictionPressureById(id);
//        if (predictionPressure != null) {
//            predictionPressure.setSoftDelete(0);
//            predictionPressureMapper.updatePredictionPressure(predictionPressure);
//        }
//
//    }
//
//    /**
//     * 批量软删除
//     */
//    @Override
//    public void softDeletePredictionPressureByIds(Long[] ids) {
//        List<PredictionPressure> predictionPressures = predictionPressureMapper.findPredictionPressureByIds(ids);
//
//        if (predictionPressures.size() > 0) {
//            for (PredictionPressure predictionPressure :predictionPressures){
//                predictionPressure.setSoftDelete(0);
//            }
//
//            predictionPressureMapper.updatePredictionPressures(predictionPressures);
//        }
//    }
        @Override
        public PredictionPressureDetailDTO getPressureDetail(Long id) {
            PredictionPressure predictionPressure;

            // 父级类
            PredictionPressureDetailDTO predictionPressureDetailDTO = new PredictionPressureDetailDTO();

            // 父级详情
            predictionPressure = predictionPressureMapper.findPredictionPressureById(id);
            predictionPressureDetailDTO.setPredictionPressureDetail(predictionPressure);
            return predictionPressureDetailDTO;
        }

        @Override
        public PredictionPressure calculatePredictionPressure(PredictionPressure predictionPressure){
            //计算
            predictionPressure.setAverageDensity(1.0 * (predictionPressure.getWellHeadDensity() + predictionPressure.getWellBottomDensity()) / 2);
            predictionPressure.setColumnPressure(9.8 * predictionPressure.getAverageDensity() * predictionPressure.getInjectionDepth() / 1000);
            predictionPressure.setDensityRatio(1.00 * predictionPressure.getWellHeadDensity() / predictionPressure.getWellBottomDensity());
            predictionPressure.setValueA(1.0 * predictionPressure.getInjectionLength() / 2 * Math.sqrt(0.5 + Math.sqrt(0.25 + Math.pow((2.0 * 150 / predictionPressure.getInjectionLength()), 4))));
            predictionPressure.setMolecularPart(Math.log((predictionPressure.getValueA() + Math.sqrt(Math.pow(predictionPressure.getValueA(), 2) - Math.pow(1.0 * predictionPressure.getInjectionLength() / 2, 2))) / (1.0 * predictionPressure.getInjectionLength() / 2)) + (predictionPressure.getInjectionThickness() / predictionPressure.getInjectionLength()) * Math.log(predictionPressure.getInjectionThickness() / (2 * 3.14 * 0.1)));
            if(predictionPressure.getWellType()=="horizontal_well") {
                predictionPressure.setProductionPressureDvalue(predictionPressure.getWellBottomViscosity() * predictionPressure.getMolecularPart() * (predictionPressure.getDailyInjection() * 1000 / (1.0 * (predictionPressure.getWellBottomDensity() * 1000)) * Math.pow(10, 6) / 24 / 60 / 60) / (2 * 3.14 * (predictionPressure.getPermeability() / 1000) * (predictionPressure.getInjectionThickness() * 100)) / 10);
            }
            else{
                predictionPressure.setProductionPressureDvalue(predictionPressure.getWellBottomViscosity() * Math.log((150/0.1)) * (predictionPressure.getDailyInjection() * 1000 /  (predictionPressure.getWellBottomDensity() * 1000) * Math.pow(10, 6) / 24 / 60 / 60) / (2 * 3.14 * (predictionPressure.getPermeability() / 1000) * (predictionPressure.getInjectionThickness() * 100)) / 10);
            }
            predictionPressure.setFlowingPressure(predictionPressure.getProductionPressureDvalue() + predictionPressure.getFormationPressure());
            predictionPressure.setInjectionPressure(predictionPressure.getFlowingPressure() - predictionPressure.getColumnPressure());
            predictionPressure.setFactorPressure(predictionPressure.getInjectionPressure() * 1.2);
            //取两位小数
            predictionPressure.setWellBottomDensity((double) Math.round(predictionPressure.getWellBottomDensity() * 10000) / 10000);
            predictionPressure.setWellBottomViscosity((double) Math.round(predictionPressure.getWellBottomViscosity() * 10000) / 10000);
            predictionPressure.setAverageDensity((double) Math.round(predictionPressure.getAverageDensity() * 100) / 100);
            predictionPressure.setColumnPressure((double) Math.round(predictionPressure.getColumnPressure() * 100) / 100);
            predictionPressure.setDensityRatio((double) Math.round(predictionPressure.getDensityRatio() * 100) / 100);
            predictionPressure.setValueA((double) Math.round(predictionPressure.getValueA() * 100) / 100);
            predictionPressure.setMolecularPart((double) Math.round(predictionPressure.getMolecularPart() * 100) / 100);
            predictionPressure.setProductionPressureDvalue((double) Math.round(predictionPressure.getProductionPressureDvalue() * 100000) / 100000);
            predictionPressure.setFlowingPressure((double) Math.round(predictionPressure.getFlowingPressure() * 100) / 100);
            predictionPressure.setInjectionPressure((double) Math.round(predictionPressure.getInjectionPressure() * 100) / 100);
            predictionPressure.setFactorPressure((double) Math.round(predictionPressure.getFactorPressure() * 100) / 100);
            return predictionPressure;
        }
}
